#include "Game.h"
#include <cstdio>
#include <iostream>
#include <string>
#include <fstream>
#include <time.h>

#include "Locations/Location.h"
#include "Locations/Indoors.h"
#include "Locations/Outdoors.h"

#include "Characters/Wizard.h"
#include "Characters/Barbarian.h"
#include "Characters/Paladin.h"

#include "CharCreate.h"

Game::Game():
stopped(false),
current_loc(NULL),
player(NULL)
{

	print_welcome_message();
}

Game::~Game()
{
	print_exit_message();
}

std::string Game::create_begin_story()
{
	std::string story = "Once upon a time there was a ";
	story += player->race;
	story +=  " who should kill Gandalf\n\nYou are ";
	if(player->getGender()){
		story += "him...";
	}
	else{
		story += "her...";
	}
	return story;
}

std::string Game::create_end_story()
{
	return std::string("Gandalf died...\nBecause of this Sauron later became ruler of Middle earth.\nNo one ever rejoiced again.\n\nAlso you got killed by the hobbits.\nYou were remembered as the most evil ") + player->race + std::string(" in the history of middle earth. The one who destroyed all hope.") ;
}

void Game::print_welcome_message()
{
	speak("Welcome to game");
}

void Game::print_exit_message()
{
	speak("Goodbye, cruel world :(");
}

void Game::print_begin_message()
{
	speak(begin_story);
}

void Game::print_end_message()
{
	speak(end_story);
}

void Game::print_main_menu()
{
	std::cout << "-----------";
	speak("Main menu----------");
	printf("Commands:\nnew game: Start new game \nload game: Load Game\nhelp: Print this menu\nexit: Exit game\n");
}

void Game::run()
{
	print_main_menu();
	while(!stopped)
	{
		auto temp = get_alternatives();
		std::vector<std::string> input = read(temp, "What would you like to do? (help for options)");
		parseInput(input);
	}
}

void Game::parseInput(std::vector<std::string> input)
{
	if(input.size() == 0)
	{
		return;
	}
	if(input.size() == 1)
	{
		if(input[0].compare("help") == 0)
		{
			print_main_menu();
		}
		if(input[0].compare("exit") == 0)
		{
			stop();
		}
	}
	if(input.size() == 2)
	{
		if(input[1].compare("game") == 0)
		{
			if(input[0].compare("new") == 0)
			{
				createNewGame();
			}
			if(input[0].compare("load") == 0)
			{
				loadGame();
			}
			gameloop();
		}
	}
}

void Game::loadGame()
{
	bool answered = false;
	std::string savename;
	while(!answered)
	{
		speak("What game do you want to load? (exit to return to main menu)");
		std::cout << "Games:" << std::endl;
		std::vector<std::string> names = get_save_files();
		for(size_t i = 0 ; i< names.size() ; i++)
		{
			std::cout << names[i] << std::endl;
		}
		std::cin >> savename;
		// empty cin
		std::string s; 
		getline(std::cin, s);
		if(savename.size() == 0)
		{
			speak("Empty name not allowed");
		}
		else if(savename.compare("exit") == 0)
		{
			return;
		}
		else
		{
			answered = load(*this, savename);
		}
	}
}

void Game::createNewGame()
{
	player = createCharacter();
	
	//current_loc = new Indoors(player, "Bag End", "Frodo lives here");
	//current_loc->set_visited(true);
	//Character* gandalf = new Wizard("Gandalf", "Human", true, false, Progress::ach(KILL_GANDALF, 100));
	//Weapon* staff = new Weapon("Staff", 45, 45, 32, 65, 1, 10);
	//Weapon* staff2 = new Weapon("Staff", 45, 45, 32, 65, 1, 10);
	//gandalf->equipItem(*staff, false);
	//dialog d1({{TALK_GANDALF, false}, {COMPLETE_GANDALF, false}}, "Talk to me again and I will reward you", TALK_GANDALF);
	//dialog d2({{TALK_GANDALF, true},{COMPLETE_GANDALF, false}} , "Here take my staff", {COMPLETE_GANDALF, 10, staff2});
	//dialog d3({{TALK_GANDALF, true},{COMPLETE_GANDALF, true}}, "You got my staff, now be gone!", NONE);
	//gandalf->setDialogs({d1,d2,d3});
	//current_loc->add_character(gandalf);
	
	//// Neighbor
	//Location* neighbor_loc = new Outdoors(NULL, "The Shire", "Home of the hobbits");
	//neighbor_loc->set_visited(false);
	//neighbor_loc->add_character(new Barbarian("Conan", "Human", true));
	//neighbor_loc->add_character(new Paladin("Sauron", "EvilGuy", true, true));
	//neighbor_loc->add_neighbor("through door", current_loc);
		
	//current_loc->add_neighbor("through door",neighbor_loc);
	
	//Weapon* weapon = new Weapon("Awesome Sword", 100, 100, 100, 100, 100, 100);
	//current_loc->add_item(weapon);
	//OtherItem* item = new OtherItem("Gold ring", 0, 0, 100, 100, 0, 0, 0);
	//current_loc->add_item(item);
	//OtherItem* item1 = new OtherItem("ring1", 0, 0, 100, 100, 0, 0, 0);
	//current_loc->add_item(item1);
	//OtherItem* item2 = new OtherItem("ring2", 0, 0, 100, 100, 0, 0, 0);
	//current_loc->add_item(item2);
	//OtherItem* item3 = new OtherItem("ring3", 0, 0, 100, 100, 0, 0, 0);
	//current_loc->add_item(item3);
	
	//addLocation(current_loc, neighbor_loc, NULL);
	
	
	
	
	current_loc = new Indoors(player, "a small room", "The room is dark and damped, there doesn't look to be any windows either. \n\nThere is also a bed... that you dont see because it is dark.");
	// Items
	Weapon * dagger = new Weapon("shiny dagger", 0,0,0,10, 10,0);
	current_loc->add_item(dagger);
	
	Outdoors* out1 = new Outdoors(NULL, "a little garden", "The garden is filled with beautiful flowers");
	//Character
	Paladin* elrond = new Paladin("Elrond", "elf", true, false, NONE, 35, 10);
	dialog d1({{TALK_ELROND, false}, {KILLED_TROLL, false}, {GET_KEY, false}}, "Kill the troll that has been bothering the villagers", TALK_ELROND);
	dialog d2({{TALK_ELROND, true},{KILLED_TROLL, false}, {GET_KEY, false}} , "Have you killed the troll yet", NONE);
	dialog d3({{KILLED_TROLL, true}, {GET_KEY, false}}, "Thank you very much for killing the troll here is a key to the palace", GET_KEY);
	dialog d4({{KILLED_TROLL, true}, {GET_KEY, true}}, "Thank you for you help. I have nothing more to say to you", NONE);
	elrond->setDialogs({d1,d2,d3, d4});
	Weapon* awesome_sword = new Weapon("Awesome Sword", 100, 100, 100, 100, 100, 100);
	elrond->equipItem(*awesome_sword, false);
	out1->add_character(elrond);
	
	Outdoors* out2 = new Outdoors(NULL, "an old campground", "There is was campfire here. There is also a rugged tent");
	Weapon* badass_sword = new Weapon("Bad-Ass Sword", 0, 0, 0, 20, 20, 0);
	Barbarian * orc = new Barbarian("Ukrash", "orc", true, false, {NONE, 20, badass_sword}, 10);
	dialog d5({}, "Go away puny hero", NONE);
	orc->setDialogs({d5});
	out2->add_character(orc);
	
	Indoors* ind1 = new Indoors(NULL, "a damp hole in the ground", "... or a dungeon.\nThis is surely a trolls hole");
	Armor* troll_armor = new Armor("Ugly plate shield", 0,0,0,20,20);
	Barbarian * troll = new Barbarian("Narg", "troll", true, true, {KILLED_TROLL, 20, troll_armor}, 10);
	OtherItem* bronzering = new OtherItem("bronze ring", 0,0,0,0,0,0,0);
	troll->equipItem(*bronzering, false);
	ind1->add_character(troll);
	
	Indoors* ind2 = new Indoors(NULL, "big palace", "I believe a wizard lives here.");
	Weapon* staff = new Weapon("Staff", 20, 0, 0, 0, 20, 0);
	Character* gandalf = new Wizard("Gandalf", "Human", true, false, Progress::ach(KILL_GANDALF, 100));
	dialog d6({{TALK_GANDALF, false}, {COMPLETE_GANDALF, false}}, "Talk to me again and I will reward you", TALK_GANDALF);
	dialog d7({{TALK_GANDALF, true},{COMPLETE_GANDALF, false}} , "Here take my staff", {COMPLETE_GANDALF, 10, staff});
	dialog d8({{TALK_GANDALF, true},{COMPLETE_GANDALF, true}}, "You know you have to kill me in order to complete the game", NONE);
	gandalf->setDialogs({d6,d7,d8});
	ind2->add_character(gandalf);
	
	current_loc->add_neighbor("through door", out1);
	out1->add_neighbor("east", out2);
	out1->add_neighbor("into hut", current_loc);
	out1->add_neighbor("to palace", ind2, GET_KEY);
	out2->add_neighbor("into hole", ind1);
	out2->add_neighbor("west", out1);
	ind1->add_neighbor("outside", out2);
	ind2->add_neighbor("to garden", out1);

	addLocation(current_loc, out1, out2, ind1, ind2 ,NULL);

	// print game story
	begin_story = create_begin_story();
	print_begin_message();
}

void Game::addLocation(Location* first_loc, ...)
{
	va_list ap;
	va_start(ap, first_loc);
	while (first_loc)
	{
		locations.push_back(first_loc);
		first_loc = va_arg(ap, Location *);
    }
	va_end(ap);
}

void Game::save_game()
{
	bool answered = false;
	while(!answered)
	{
		speak("Do you want to save your progress? (y/n)");
		std::string in;
		std::cin >> in;
		if(in.compare("y") == 0)
		{
			speak("What name do you want to save the game as? (exit to return to main menu)");
			std::string savename;
			std::cin >> savename;
			// empty cin
			std::string s; 
			getline(std::cin, s);
			if(savename.size() == 0)
			{
				speak("Empty name not allowed");
			}
			if(savename.compare("exit") == 0)
			{
				return;
			}
			else 
			{
				answered = save(*this, savename);
			}
		}
		if(in.compare("n") == 0)
		{
			answered = true;
		}
	}
	return;
}

void Game::delete_game()
{
	current_loc = NULL;
	for(size_t i = 0 ; i < locations.size() ; i++)
	{
		delete locations[i];
	}
	locations.clear();
	delete player;
	player = NULL;
}

void Game::gameloop()
{
	while(current_loc != NULL)
	{
		Location * temp = current_loc->run();
		if(player->achieved(KILL_GANDALF))
		{
			end_story = create_end_story();
			print_end_message();
			break;
		}
		if(temp == NULL && player->getHP() > 0)
		{
			save_game();
		}
		current_loc = temp;
	}
	delete_game();
	print_main_menu();
}

std::vector<cmdalt> Game::get_alternatives()
{
	std::vector<cmdalt> alternatives;
	{
		cmdalt alt;
		alt.first = "new";
		alt.second = {"game"};
		alternatives.push_back(alt);
	}
	{
		cmdalt alt;
		alt.first = "load";
		alt.second = {"game"};
		alternatives.push_back(alt);
	}
	{
		cmdalt alt;
		alt.first = "help";
		alt.second = {};
		alternatives.push_back(alt);
	}
	{
		cmdalt alt;
		alt.first = "exit";
		alt.second = {};
		alternatives.push_back(alt);
	}
	return alternatives;
}

void Game::stop()
{
	stopped = true;
}

using namespace std;
int main(int argc, char ** argv)
{
	srand ( time(NULL) );
	Game g;
	g.run();
}
